package com.ys.p4Queue队列;

/**
 * 描述: 使用数组模拟实现队列:
 * 数组实现的队列,是一种有限资源,无限竞争的 队列模式
 *  循环队列,可以一直使用
 *  [] 数组资源有限, 访问者无限,不管可以一直循环下去使用这个有限的资源,但是必须排队
 * @author CodeYang
 * @version 2020/12/26 0:40
 */
public class ArrayQueue<E> implements  Queue<E>{
    /**
     * 定义一个数组,用于保存队列的元素
     */
    private E[] elementData;
    /**
     * 定义一个遍历,用于指向队首元素
     */
    private int front;
    /**
     * 定义一个遍历用于指向,队尾元素
     */
    private int rear;

    /**
     *  无参构造方法,默认设置队列长度尾5
     */
    public ArrayQueue() {
        this(5);
    }

    /**
     * 构造方法,初始化成员变量,--队列
     * @param cap
     */
    public ArrayQueue(int cap) {
        if (cap<0){
            throw  new IllegalArgumentException("参数不合法,cap:"+cap);
        }
       elementData = (E[]) new Object[cap];
    }

    /**
     * 返回队列中的实际元素个数
     * @return 返回队列的实际元素的个数
     */
    public int size(){
        // 两种情况:
        // 队尾 指针> =队首 指针
        if (rear >= front){
            return rear -front;
        } else {
            // 队首 > 队尾 front - rear的结果就是队列空闲的个数。
            return elementData.length -(front - rear);
        }

    }

    /**
     * 在队尾添加元素
     *
     * @param element
     * @return
     */
    @Override
    public boolean offer(E element) {
        // 队满 返回false
        if (isFull()){
            return false;
        }
        // 队未满
        elementData[rear] = element;
        // 更新rear的值 递增,循环
        rear = (rear +1) % elementData.length;
        // 返回入队成功
        return true;
    }

    /**
     * 获得队首的元素，不会执行出队操作
     *
     * @return
     */
    @Override
    public E peek() {
        // 队列为空,返回null
        if (isEmpty()){
            return null;
        }
        // 不为空空返回 front 队首元素
        return elementData[front];
    }

    /**
     * 获得队首的元素，并且队首元素出队
     *  出队,先进后出
     * @return
     */
    @Override
    public E poll() {
        if (isEmpty()){
            return null;
        }

        // 保存队首元素
        E oldValue = elementData[front];
        // 设置 队首元素为null
        elementData[front] =null;
        // 指向ffont 执行++
        front = (front +1) % elementData.length;
        return oldValue;
    }

    /**
     * 判断队列是否为空。
     * 队首: font == 队尾: rear 时证明队列为空
     * @return 如果队列为空，则返回true；如果队列不为空，则返回false。
     */
    @Override
    public boolean isEmpty() {
        return front == rear;
    }

    /**
     *  判断队满:(有一个[] 不使用)
     * @return
     */
    private boolean isFull(){
        //
        return front == (rear +1 ) % elementData.length;
    }
}
